package cn.kgc.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.kgc.dto.Attr;
import cn.kgc.dto.SearchParam;
import cn.kgc.dto.SearchResult;
import cn.kgc.entity.SkuEsModel;
import cn.kgc.mapper.SkuEsModelElasticsearchRepository;
import cn.kgc.service.EsSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.nested.NestedAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.nested.ParsedNested;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>添加描述信息</p>
 *
 * @author 卢传琪
 */
@Service("esSearchService")
@Slf4j
public class EsSearchServiceImpl implements EsSearchService {
    @Resource
    private SkuEsModelElasticsearchRepository skuEsModelElasticsearchRepository;
    @Override
    public SearchResult search(SearchParam searchParam) {
        //分页查询条件
        Pageable pageable=PageRequest.of(searchParam.getPageNum(),10);
        //普通的查询条件
        BoolQueryBuilder queryBuilder=QueryBuilders.boolQuery();
        //根据二级标题查询
        if(StringUtils.isNotBlank(searchParam.getKeyword())){
            queryBuilder.must(QueryBuilders.matchQuery("subTitle",searchParam.getKeyword()));
        }
        //根据分类ID查询
        if (searchParam.getCategoryId()!=0){
            queryBuilder.filter(QueryBuilders.termQuery("categoryId",searchParam.getCategoryId()));
        }
        //根据品牌ID查询
        if (CollectionUtil.isNotEmpty(searchParam.getBrandId())){
            searchParam.getBrandId().forEach(brandId->{
                queryBuilder.filter(QueryBuilders.termQuery("brandId",brandId));
            });
        }

        if (StringUtils.isNotBlank(searchParam.getSkuPrice())){
            String tempMinPrice=searchParam.getSkuPrice().split("_")[0];
            RangeQueryBuilder rangeQueryBuilder=QueryBuilders.rangeQuery("skuPrice");
            long minPrice=0;
            if (StringUtils.isNotBlank(tempMinPrice)){
                minPrice=Long.parseLong(tempMinPrice);
            }
            long maxPrice=99999999;
            String tempMaxPrice=searchParam.getSkuPrice().split("_")[1];
            if (StringUtils.isNotBlank(tempMaxPrice)){
                maxPrice=Long.parseLong(tempMaxPrice);
            }
            rangeQueryBuilder.gte(minPrice).lte(maxPrice);
            queryBuilder.filter(rangeQueryBuilder);
        }
        //是否有库存
        queryBuilder.filter(QueryBuilders.termQuery("hasStock",searchParam.isHasStock()));
        //属性的嵌套查询(属性的类型是Nested)
        if (CollectionUtil.isNotEmpty(searchParam.getAttrs())){
            //属性编号_属性的值
            for (String attr : searchParam.getAttrs()) {
                long arrtId=Long.parseLong(attr.split("_")[0]);
                String attrValue=attr.split("_")[1];
                queryBuilder.filter(QueryBuilders.nestedQuery("attrList",
                        QueryBuilders.boolQuery()
                                .filter(QueryBuilders.termQuery("attrList.attrId",arrtId))
                                .filter(QueryBuilders.termQuery("attrList.attrValue",attrValue)),
                        ScoreMode.None));
            }
        }
        //排序规则
        FieldSortBuilder fieldSortBuilder=SortBuilders.fieldSort(searchParam.getSort()).order(SortOrder.DESC);
        //聚合查询
        //品牌聚合
        TermsAggregationBuilder brandAggregation=AggregationBuilders.terms("brand_id_aggs").field("brandId").size(10)
                .subAggregation(AggregationBuilders.terms("brand_name_aggs").field("brandName").size(10));
        //todo 分类聚合 属性聚合
        //分类聚合
        TermsAggregationBuilder categoryAggregation=AggregationBuilders.terms("category_id_aggs").field("categoryId").size(10)
                .subAggregation(AggregationBuilders.terms("category_name_aggs").field("categoryName").size(10));
        //属性聚合
        NestedAggregationBuilder attrAggregation = AggregationBuilders.nested("attr_aggs", "attrList");
        attrAggregation.subAggregation(AggregationBuilders.terms("attr_id_aggs").field("attrList.attrId")
                .subAggregation(AggregationBuilders.terms("attr_name_aggs").field("attrList.attrName")
                        .subAggregation(AggregationBuilders.terms("attr_value_aggs").field("attrList.attrValue"))
                ));
        NativeSearchQuery searchQuery=new NativeSearchQueryBuilder()
                .withPageable(pageable)
                .withSort(fieldSortBuilder)
                .withQuery(queryBuilder)
                .addAggregation(brandAggregation)
                .addAggregation(categoryAggregation)
                .addAggregation(attrAggregation).build();
        //执行查询操作
        AggregatedPage<SkuEsModel> aggregatedPage = (AggregatedPage<SkuEsModel>) skuEsModelElasticsearchRepository.search(searchQuery);
        //总记录数
        long total=aggregatedPage.getTotalElements();
        //总页数
        long totalPages=aggregatedPage.getTotalPages();
        //当前页数据
        List<SkuEsModel> skuEsModels = aggregatedPage.getContent();
        //获得聚合数据
        SearchResult searchResult=new SearchResult();
        Terms brandTerms = (Terms)aggregatedPage.getAggregation("brand_id_aggs");
        List<SearchResult.BrandVO> brandVOList=new ArrayList<>();
        for (Terms.Bucket bucket : brandTerms.getBuckets()) {
            SearchResult.BrandVO brandVO=new SearchResult.BrandVO();
            long brandId = Long.parseLong(bucket.getKeyAsString());
            brandVO.setBrandId(brandId);
            Terms terms1= (Terms) bucket.getAggregations().asMap().get("brand_name_aggs");
            for (Terms.Bucket terms1Bucket : terms1.getBuckets()) {
                String brandName = terms1Bucket.getKeyAsString();
                brandVO.setBrandName(brandName);
            }
            brandVOList.add(brandVO);
        }
        Terms categoryTerms=(Terms)aggregatedPage.getAggregation("category_id_aggs") ;
        List<SearchResult.CategoryVo> categoryVoList=new ArrayList<>();
        for (Terms.Bucket bucket : categoryTerms.getBuckets()) {
            SearchResult.CategoryVo categoryVo=new SearchResult.CategoryVo();
            long categoryId=Long.parseLong(bucket.getKeyAsString());
            categoryVo.setCategoryId(categoryId);
            Terms terms1=(Terms) bucket.getAggregations().asMap().get("category_name_aggs");
            for (Terms.Bucket terms1Bucket : terms1.getBuckets()) {
                String categoryName=terms1Bucket.getKeyAsString();
                categoryVo.setCategoryName(categoryName);
            }
            categoryVoList.add(categoryVo);
        }
        List<SearchResult.AttrVo> attrVoList=new ArrayList<>();
        Aggregation productAttrs= aggregatedPage.getAggregations().get("attr_aggs");
        for (Terms.Bucket attr_id_aggs : ((ParsedLongTerms) ((ParsedNested) productAttrs).getAggregations().get("attr_id_aggs")).getBuckets()) {
            SearchResult.AttrVo attrVo = new SearchResult.AttrVo();
            String idKey=attr_id_aggs.getKeyAsString();
            attrVo.setAttrId(Long.parseLong(idKey));
            for (Terms.Bucket attr_name_aggs : ((ParsedStringTerms) (attr_id_aggs.getAggregations().get("attr_name_aggs"))).getBuckets()) {
                attrVo.setAttrName(attr_name_aggs.getKey().toString());
                List<String> attrValues = new ArrayList<>();
                for (Terms.Bucket attr_value_aggs : ((ParsedStringTerms) attr_name_aggs.getAggregations().get("attr_value_aggs")).getBuckets()) {
                    attrValues.add(attr_value_aggs.getKeyAsString());
                }
                attrVo.setAttrValue(attrValues);
            }
            attrVoList.add(attrVo);
        }
        searchResult.setBrandVOList(brandVOList);
        searchResult.setTotal(total);
        searchResult.setTotalPages(totalPages);
        searchResult.setSkuEsModelList(skuEsModels);
        searchResult.setPageNum(searchParam.getPageNum());
        searchResult.setCategoryVoList(categoryVoList);
        searchResult.setAttrVoList(attrVoList);
        return searchResult;
    }
}
